home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
askrunlevel
/
runlevels.c
< prev
Wrap
C/C++ Source or Header
|
1996-03-02
|
10KB
|
375 lines
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "../misc/misc.h"
#include "askrunlevel.h"
#include "internal.h"
#include "../userconf/userconf.h"
#include "../netconf/netconf.h"
#include "../paths.h"
#include "askrunlevel.m"
static HELP_FILE help_default (HELP_ASKRUN,"default");
static HELP_FILE help_define (HELP_ASKRUN,"define");
// Some keys for /etc/conf.linuxconf
static const char ASKRUNLEVEL[]="askrunlevel";
static const char TIMEOUT[]="timeout";
static const char DEFMODE[]="defmode";
static const char K_RUNLEVEL[]="runlevel";
#define NB_RUNLEVEL 6
/*
Write the configuration parameter into /etc/askrunlevel.conf
*/
static int askrunlevel_saveparm(ASK_PARM &parm)
{
linuxconf_replace (ASKRUNLEVEL,TIMEOUT,parm.timeout);
linuxconf_replace (ASKRUNLEVEL,DEFMODE,parm.defmode);
return linuxconf_save();
}
/*
Write the configuration parameter into /etc/askrunlevel.conf
*/
void askrunlevel_readparm(ASK_PARM &parm)
{
parm.timeout = linuxconf_getvalnum(ASKRUNLEVEL,TIMEOUT,0);
parm.defmode = linuxconf_getvalnum(ASKRUNLEVEL,DEFMODE,4);
/* #Specification: askrunlevel / configuration file
askrunlevel stores its default operation mode into
/etc/conf.linuxconf. This file is optionnal. The
default setup is:
runlevel 5, netlevel 0 -> text mode, no networking
No timeout (askrunlevel will wait forever)
*/
}
/*
parse one line of /etc/conf.linuxconf
*/
PRIVATE void RUNLEVELS::parse (const char *str, RUNLEVEL *ptrun)
{
/* #Specification: askrunlevel / runlevel definition / /etc/conf.linuxconf
The definitions of the different operation mode are
stored in /etc/conf.linuxconf with the following format
#
askrunlevel.runlevel init net graphic_mode title ...
Where,
init (runlevel for /sbin/init) is one of
1,2,3,4,5,6,S
net is 0 1 or 2 for no network, client network and
server respectivly
graphic is 0 1 or 2 for text mode, graphic mode (workstation)
and X terminal respectivly.
#
*/
str = str_skip(str);
ptrun->init_runlevel = *str++;
str = str_skip(str);
ptrun->netconf_runlevel = atoi(str++);
str = str_skip(str);
ptrun->graphic_level = atoi(str++);
ptrun->title.setfrom (str_skip(str));
}
/*
Definition of the different runlevels available
*/
PUBLIC RUNLEVELS::RUNLEVELS(
int graphic_ok,
int net_ok)
{
static struct {
const char *mode;
const char *title;
}default_tbrun[]={
{"4 2 1",MSG_U(M_GR_NET,"Graphic & Network")},
{"4 0 1",MSG_U(M_GRONLY,"Graphic only")},
{"2 1 2",MSG_U(M_XTERMINAL,"X terminal")},
{"5 2 0",MSG_U(M_TX_NET,"Text mode & Network")},
{"3 0 0",MSG_U(M_TXONLY,"Text mode only")},
{"S 0 0",MSG_U(M_MAINTENANCE,"Maintenance mode")},
};
SSTRINGS lst;
/* #Specification: askrunlevel / operation mode / definition
The definition of the six different operation
mode are defined in /etc/conf.linuxconf
*/
linuxconf_getall (ASKRUNLEVEL,K_RUNLEVEL,lst,0);
RUNLEVEL *ptrun = tbrun;
for (int i=0; i<NB_RUNLEVEL; i++, ptrun++){
if (i<lst.getnb()){
parse (lst.getitem(i)->get(),ptrun);
}else{
char buf[100];
sprintf (buf,"%s %s",default_tbrun[i].mode,default_tbrun[i].title);
parse (buf,ptrun);
}
ptrun->graphic_err = ptrun->graphic_level > 0
&& !graphic_ok;
ptrun->net_err = ptrun->netconf_runlevel > 0 && !net_ok;
char buf[80];
ptrun->title.copy(buf);
if (ptrun->graphic_err || ptrun->net_err){
strcat (buf," ");
strcat (buf,MSG_U(M_NOTCONF,"(Not configured)"));
}
tbmenu[i].setfrom (buf);
}
}
PUBLIC RUNLEVELS::~RUNLEVELS()
{
}
PUBLIC void RUNLEVELS::save()
{
linuxconf_removeall (ASKRUNLEVEL,K_RUNLEVEL);
RUNLEVEL *ptrun = tbrun;
for (int i=0; i<NB_RUNLEVEL; i++, ptrun++){
char buf[80];
sprintf (buf,"%c %d %d %s"
,ptrun->init_runlevel
,ptrun->netconf_runlevel
,ptrun->graphic_level
,ptrun->title.get());
linuxconf_add (ASKRUNLEVEL,K_RUNLEVEL,buf);
}
linuxconf_save();
}
PUBLIC void RUNLEVELS::setmenu (
const char *menuopt[])
{
int ii=1;
for (unsigned i=0; i<sizeof(tbrun)/sizeof(tbrun[0]); i++, ii+=2){
menuopt[ii] = tbmenu[i].get();
}
}
/*
Record the selected runlevels in the different files used later.
*/
PUBLIC void RUNLEVELS::setlevel(int choice)
{
/* #Specification: askrunlevel / talking to init / compatibitily
Most init expect to receive their new runlevel in
/etc/initrunlvl. Some do expect it in /var/run/initrunlvl.
I feel the later make more sens. Anyway, askrunlevel write
at both places.
The askrunlevel utility was originally called by init
directly. It has been found that askrunlevel could be called
at the end of /etc/rc.d/rc.S (or whatever is on your system)
without any special support from init. The current askrunlevel
is playing is calling init to select the proper runlevel.
*/
static char *tb[]={
VAR_RUN_INITRUNLEVEL,
ETC_INITRUNLEVEL
};
char levelstr[2];
levelstr[0] = tbrun[choice].init_runlevel;
levelstr[1] = '\0';
for (int i=0; i<2; i++){
FILE *fout = xconf_fopen (tb[i],"w");
if (fout != NULL){
fprintf (fout,"%s\n",levelstr);
fclose (fout);
}
}
netconf_setnetlevel (tbrun[choice].netconf_runlevel);
netconf_system_if ("telinit",levelstr);
}
/*
Let the user select the default runlevel for for next run
*/
PUBLIC void RUNLEVELS::config()
{
if (perm_rootaccess(MSG_U(P_BOOTMODE,"change the boot mode"))){
ASK_PARM parm;
askrunlevel_readparm (parm);
DIALOG dia;
dia.newf_title ("",MSG_U(T_DEFOPER,"Default operation mode"));
char choice = parm.defmode;
for (int i=0; i<5; i++){
dia.newf_radio ("",choice,i,tbmenu[i].get());
}
dia.newf_title ("","");
dia.newf_num (MSG_U(F_DELAY,"Delay to activate"),parm.timeout);
if (dia.edit (MSG_U(T_BOOTCMODE,"Boot mode configuration")
,MSG_U(I_BOOTCMODE,"Select the default operation mode\n"
"and a timeout. A timeout of 0 means\n"
"to wait forever.\n")
,help_default.getpath()
,0)==MENU_ACCEPT){
parm.defmode = choice;
askrunlevel_saveparm (parm);
RUNLEVEL *ptrun = tbrun + choice;
if (ptrun->graphic_err || ptrun->net_err){
xconf_notice(MSG_U(N_NOTCONF,"This runlevel is not yet"
" configured"));
}
}
}
}
/*
Initialise one combo box field
*/
static void runlevels_setcombo (
DIALOG &dia,
const char *title,
SSTRING &s,
int curval,
const char *values[])
{
s.setfrom (values[curval]);
FIELD_COMBO *comb = dia.newf_combo (title,s);
for (int i=0; values[i] != NULL; i++){
comb->addopt (values[i]);
}
}
/*
Get the index of a value in a table
*/
static int runlevels_locate (
const char *values[],
SSTRING &s,
int ¬found, // Will be set to id if not found
// Will be left unchanged if found.
int id)
{
const char *pt = s.get();
int ret = 0;
int i;
for (i=0; values[i] != NULL; i++){
if (stricmp(values[i],pt)==0){
ret = i;
break;
}
}
if (values[i] == NULL) notfound = id;
return ret;
}
PUBLIC void RUNLEVELS::define()
{
/* #Specification: askrunlevel / runlevel definition
askrunlevel let the user select one of six operation
mode. It also let the user redefine (and rename)
those operation mode. The user can change any of
the six proposed mode.
The name (title), the runlevel (for /sbin/init)
and the network mode (for netconf) and the graphic
mode (nographic, Workstation and X terminal) can
be selected for each mode.
*/
DIALOG dia;
struct TBSTR{
SSTRING init;
SSTRING net;
SSTRING graphic;
}tbstr[NB_RUNLEVEL];
static const char *tbinit[] = {
"1","2","3","4","5","6",
"A","B","C","D","E","F",
"Maintenance",
NULL
};
static const char *tbnet[]={
MSG_U(M_NONET,"No network"),
MSG_U(M_CLIENT,"Client"),
MSG_U(M_SERVER,"Server"),
NULL
};
static const char *tbgraphic[]={
MSG_U(M_TEXTMODE,"Text mode"),
MSG_U(M_WORKSTATION,"Workstation"),
MSG_U(M_XTERM,"X terminal"),
NULL
};
RUNLEVEL *ptrun = tbrun;
TBSTR *ptstr = tbstr;
for (int i=0; i<NB_RUNLEVEL; i++, ptrun++, ptstr++){
dia.newf_title ("","");
dia.newf_str (MSG_U(F_TITLE,"Title"),ptrun->title);
int init_r = ptrun->init_runlevel;
if (init_r == 'S'){
init_r = 12;
}else if (isdigit(init_r)){
init_r -= '1';
}else{
init_r = (init_r - 'A') + 6;
}
runlevels_setcombo (dia,MSG_U(F_RUNLEVEL,"init runlevel")
,ptstr->init
,init_r
,tbinit);
runlevels_setcombo (dia,MSG_U(F_NETMODE,"Network mode")
,ptstr->net
,ptrun->netconf_runlevel
,tbnet);
runlevels_setcombo (dia,MSG_U(F_GRMODE,"Graphic mode")
,ptstr->graphic
,ptrun->graphic_level
,tbgraphic);
}
int pos = 1;
while (1){
if (dia.edit (MSG_U(T_RUNDEF,"Runlevels definition")
,MSG_U(I_RUNDEF,"You are allowed to name\n"
"the different runlevel for this machine\n")
,help_define.getpath()
,pos) != MENU_ACCEPT){
dia.restore();
break;
}else{
ptrun = tbrun;
ptstr = tbstr;
int notfound = 0;
for (int j=0; j<NB_RUNLEVEL; j++, ptrun++,ptstr++){
int notfound_one = 0;
int init_r = runlevels_locate (tbinit
,ptstr->init
,notfound_one,2);
if (init_r == 12){
init_r = 'S';
}else if (init_r >= 6){
init_r += 'A' - 6;
}else{
init_r += '1';
}
ptrun->init_runlevel = init_r;
ptrun->netconf_runlevel = runlevels_locate (
tbnet,ptstr->net,notfound_one,3);
ptrun->graphic_level = runlevels_locate (
tbgraphic,ptstr->graphic
,notfound_one,4);
if (notfound_one){
notfound = 1;
xconf_error (MSG_U(E_IVLDEF,"Invalid definition"));
pos = j * 5 + notfound_one;
break;
}
}
if (!notfound){
save();
break;
}
}
}
}